<!doctype html>
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>2.2 - FreeMarker 手册</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="FreeMarker 手册">
<meta property="og:title" content="2.2">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="http://freemarker.org/docs/versions_2_2.html">
<link rel="canoical" href="http://freemarker.org/docs/versions_2_2.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css">
</head>
<body itemscope itemtype="https://schema.org/Code">
    <meta itemprop="url" content="http://freemarker.org/docs/">
    <meta itemprop="name" content="FreeMarker 手册">

  <!--[if lte IE 9]>
  <div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div>
  <![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://freemarker.org" role="banner">            <img itemprop="image" src="logo.png" alt="FreeMarker">
</a><ul class="tabs"><li><a href="http://freemarker.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="http://freemarker.org/docs/api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="http://freemarker.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://sourceforge.net/p/freemarker/bugs/new/" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="http://freemarker.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="toc.html" class="navigation-header">Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="toc.html"><span itemprop="name">FreeMarker 手册</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app.html"><span itemprop="name">附录</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app_versions.html"><span itemprop="name">版本历史</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="versions_2_2.html"><span itemprop="name">2.2</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div>    <div class="main-content site-width">
      <div class="content-wrapper">
  <div id="table-of-contents-wrapper" class="col-left">
      <script>var breadcrumb = ["FreeMarker 手册","附录","版本历史","2.2"];</script>
      <script src="toc.js"></script>
      <script src="docgen-resources/main.min.js"></script>
  </div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="versions_2_2_1.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_1_5.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="versions_2_2" itemprop="headline">2.2</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_240" data-menu-target="autoid_240">Non backward-compatible changes!</a></li><li><a class="page-menu-link" href="#autoid_241" data-menu-target="autoid_241">Changes in FTL (FreeMarker Template Language)</a></li><li><a class="page-menu-link" href="#autoid_242" data-menu-target="autoid_242">Changes on the Java side</a></li><li><a class="page-menu-link" href="#autoid_243" data-menu-target="autoid_243">Other changes</a></li><li><a class="page-menu-link" href="#autoid_244" data-menu-target="autoid_244">The history of the releases before the final version</a><ul><li><a class="page-menu-link" href="#autoid_245" data-menu-target="autoid_245">Differences between the final and RC2 releases</a></li><li><a class="page-menu-link" href="#autoid_246" data-menu-target="autoid_246">Differences between the RC2 and RC1 releases</a></li><li><a class="page-menu-link" href="#autoid_247" data-menu-target="autoid_247">Differences between the Preview 2 and RC1 releases</a></li><li><a class="page-menu-link" href="#autoid_248" data-menu-target="autoid_248">Differences between the Preview 1 and Preview 2
releases</a></li></ul></li></ul> </div><p>Date of release: 2003-03-27</p><p>This release introduces some really important new features.
        Unfortunately, evolution was painful again; we have a few non-backward
        compatible changes (see below). Also, for those of you awaiting
        desired native date/time type, sorry, it is still not here (because of
        some internal chaos in the team... stand by, it&#39;s coming).</p>
          



<h2 class="content-header header-section2" id="autoid_240">Non backward-compatible changes!</h2>


          <ul>
            <li>
              <p>Macros are now plain variables. This means that if you are
              unlucky and you have both a macro and another variable with the
              same name, now the variable will overwrite the macro, so your
              old template will malfunction. If you have a collection of
              common macros, you should use the new <a href="dgui_misc_namespace.html">namespace feature</a> to
              prevent accidental clashes with the variables used in the
              templates.</p>
            </li>

            <li>
              <p>With the introduction of the new <a href="dgui_misc_namespace.html">namespace support</a>,
              <code class="inline-code">global</code> and <code class="inline-code">assign</code>
              directives are no longer synonyms. <code class="inline-code">assign</code>
              creates a variable in the current <code class="inline-code">namespace</code>,
              while <code class="inline-code">global</code> creates variable that is visible
              from all namespaces (as if the variable would be in the
              data-model). Thus, the variable created with
              <code class="inline-code">assign</code> is more specific, and hides the
              variable of the same name created with
              <code class="inline-code">global</code>. As a result, if you use both
              <code class="inline-code">global</code> and <code class="inline-code">assign</code> mixed
              for the same variable in your templates, now they will
              malfunction. The solution is to search-and-replace all
              <code class="inline-code">global</code>s in your old templates with
              <code class="inline-code">assign</code>.</p>
            </li>

            <li>
              <p>The reserved hash <code class="inline-code">root</code> no longer exists
              as a predefined variable (we no longer have reserved variables).
              Use <a href="dgui_template_exp.html#dgui_template_exp_var_special">special
              variable expressions</a> to achieve similar effects. However,
              we have no equivalent replacement for <code class="inline-code">root</code>
              because of the changes in the variable scopes caused by the
              introduction of namespaces. You may should use
              <code class="inline-code">.globals</code> or
              <code class="inline-code">.namespace</code>.</p>
            </li>

            <li>
              <p>The <code class="inline-code">BeansWrapper</code> no longer exposes
              native Java arrays, booleans, numbers, enumerations, iterators,
              and resource bundles as <code class="inline-code">TemplateScalarModel</code>.
              This way, number objects wrapped through
              <code class="inline-code">BeansWrapper</code> are subject to FreeMarker&#39;s
              number formatting machinery. Also, booleans can be formatted
              using the <code class="inline-code">?string</code> built-in.</p>
            </li>

            <li>
              <p>The signature of
              <code class="inline-code">Configuration.setServletContextForTemplateLoading</code>
              has been changed: the first parameter is now
              <code class="inline-code">Object</code> instead of
              <code class="inline-code">javax.servlet.ServletContext</code>. Thus, you have
              to recompile your classes that call this method. The change was
              required to prevent class-loading failure when
              <code class="inline-code">javax.servlet</code> classes are not available and
              you would not call this method.</p>
            </li>

            <li>
              <p>This release introduces a <a href="dgui_misc_whitespace.html">parse-time white-space
              remover</a> that strips some of the typical superfluous
              white-space around FreeMarker tags and comments. <em>This
              feature is on by default!</em> Most probably this will not
              cause problems if you generate white-space neutral output like
              HTML. But if it does cause undesirable reformatting in output
              you generate, you can disable it with
              <code class="inline-code">config.setWhitespaceStripping(false)</code>. Also,
              you can enable/disable it on a per-template basis with the new
              <a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code></a>
              directive.</p>
            </li>

            <li>
              <p>Some new directives were introduced:
              <code class="inline-code">nested</code>, <code class="inline-code">import</code>,
              <code class="inline-code">escape</code>, <code class="inline-code">noescape</code>,
              <code class="inline-code">t</code>, <code class="inline-code">rt</code>,
              <code class="inline-code">lt</code>. This means that if you are unlucky and
              the text of your template contains something like
              <code class="inline-code">&lt;nested&gt;</code>, then that will be
              misinterpreted as a directive. To prevent this kind of problem
              in the future, we recommend everybody to switch from the old
              syntax to the new syntax (``strict syntax&#39;&#39;). The strict syntax
              will be the the default syntax starting from some of the later
              releases anyway. We plan to release a conversion tool for
              converting old templates. For more information please read:
              <a href="ref_depr_oldsyntax.html">模板语言参考 /废弃的 FTL 结构/老式 FTL 语法</a></p>
            </li>

            <li>
              <p>The data-model created by the
              <code class="inline-code">FreemarkerServlet</code> now uses automatic scope
              discovery, so writing
              <code class="inline-code">Application.<em class="code-color">attrName</em></code>,
              <code class="inline-code">Session.<em class="code-color">attrName</em></code>,
              <code class="inline-code">Request.<em class="code-color">attrName</em></code>
              is no longer mandatory; it&#39;s enough to write
              <code class="inline-code"><em class="code-color">attrName</em></code> (for more
              information <a href="pgui_misc_servlet.html#topic.servlet.scopeAttr">read
              this</a>). This may break an old template if that rely on the
              non-existence of certain top-level variables.</p>
            </li>

            <li>
              <p><code class="inline-code">FreemarkerServlet</code> now uses the encoding
              of the template file for the output, unless you specify the
              encoding in the <code class="inline-code">ContentType</code> init-param, such
              as <code class="inline-code">text/html; charset=UTF-8</code>.</p>
            </li>

            <li>
              <p>The format of template paths is now more restricted than
              before. The path must not use <code class="inline-code">/</code>,
              <code class="inline-code">./</code> and <code class="inline-code">../</code> and
              <code class="inline-code">://</code> with other meaning as they have in URL
              paths (or in UN*X paths). The characters <code class="inline-code">*</code>
              and <code class="inline-code">?</code> are reserved. Also, the template loader
              must not want paths starting with <code class="inline-code">/</code>. For more
              information please read: <a href="pgui_config_templateloading.html">程序开发指南/配置(Configuration)/模板加载</a></p>
            </li>

            <li>
              <p>Till now
              <code class="inline-code">TemplateTransformModel.getWriter</code> has received
              null as parameter map if the transform was called without
              parameters. From now, it will receive an empty Map instead. Note
              that the previous API documentation didn&#39;t state that it always
              receives null if there are no parameters, so hopelessly only
              very few classes exploit this design mistake.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_241">Changes in FTL (FreeMarker Template Language)</h2>


          <ul>
            <li>
              <p>User-defined directives: Transform and macro call syntax
              has been unified; they can be called in the same way, as
              user-defined directives. This also means that macros support
              named parameters and nested content (like the -- now deprecated
              -- <code class="inline-code">transform</code> directive did). For example, if
              you have a macro called <code class="inline-code">sect</code>, you may call it
              via <code class="inline-code">&lt;@sect title=&quot;Blah&quot; style=&quot;modern&quot;&gt;Blah
              blah...&lt;/@sect&gt;</code>. For more information read:
              <a href="dgui_misc_userdefdir.html">模板开发指南/其它/自定义指令</a></p>
            </li>

            <li>
              <p>Macros are now plain variables. This significantly
              simplifies FreeMarker semantics, while providing more
              flexibility; for example you can pass macros as parameters to
              other macros and transforms. As for the problem of clashing
              commonly-used-macro and variable names, we provide a more
              powerful solution: namespaces.</p>
            </li>

            <li>
              <p>Namespaces: Names-spaces are invaluable if you want to
              assemble collections (``libraries&#39;&#39;) of macros and transforms
              (and other variables), and then use them in any template without
              worrying about accidental name clashes with the application
              specific and temporary variables, or with the variables of other
              collections you want to use in the same template. This is
              extremely important if FreeMarker users want to share their
              macro/transform collections. For more information read: <a href="dgui_misc_namespace.html">模板开发指南/其它/命名空间</a></p>
            </li>

            <li>
              <p>With the introduction of namespaces our variable related
              terminology changed. As a result, <code class="inline-code">assign</code> is
              no longer synonymous with <code class="inline-code">global</code>. The
              <code class="inline-code">assign</code> directive has been undeprecated, and
              should be used instead of <code class="inline-code">global</code> almost
              everywhere. In the new approach <code class="inline-code">assign</code>
              creates variables in the current namespace, while
              <code class="inline-code">global</code> creates a variable that is visible
              from all namespaces (as if the variable were in the root of the
              data-model). A variable created with <code class="inline-code">assign</code>
              in the current namespace hides the variable of the same name
              that was created with <code class="inline-code">global</code>.</p>
            </li>

            <li>
              <p><code class="inline-code">ftl</code> directive: With this directive you
              can give information about the template for FreeMarker, like the
              encoding (charset) of the template, the used FTL syntax variant,
              etc. Also, this directive helps you to write templates that are
              less dependent on FreeMarker configuration settings, also it
              helps third-party tools to identify and correctly parse
              FreeMarker templates. For more information see: <a href="ref_directive_ftl.html#ref.directive.ftl"><code>ftl</code>
              directive</a></p>
            </li>

            <li>
              <p>White-space stripping: FreeMarker now automatically
              removes some of the typical superfluous white-spaces around
              FreeMarker tags and comments, like the indentation spaces
              before- and line-break after <code class="inline-code">&lt;#if ...&gt;</code>
              tags. For more information read: <a href="dgui_misc_whitespace.html#dgui_misc_whitespace_stripping">模板开发指南/其它/空白处理/剥离空白</a></p>
            </li>

            <li>
              <p>New directive to apply a common (&quot;escaping&quot;) expression to
              all interpolations in a block: <a href="ref_directive_escape.html#ref.directive.escape"><code>escape</code></a>.
              The name comes from the common usage of this directive for
              automatic HTML-escaping of interpolations.</p>
            </li>

            <li>
              <p>The new and preferred way of number formatting with
              <code class="inline-code">string</code> built-in is
              <code class="inline-code">foo?string(format)</code>, instead of the less
              natural <code class="inline-code">foo?string[format]</code>.</p>
            </li>

            <li>
              <p>The <code class="inline-code">string</code> built-in works for boolean
              values. For example: <code class="inline-code">${spamFilter?string(&quot;enabled&quot;,
              &quot;disabled&quot;)}</code>. For more information <a href="ref_builtins_boolean.html#ref_builtin_string_for_boolean">read the
              reference</a>.</p>
            </li>

            <li>
              <p>The default strings for outputting boolean value using the
              <code class="inline-code">string</code> built-in can be set using the
              <code class="inline-code">boolean_format</code> setting.</p>
            </li>

            <li>
              <p>Comments can be placed inside FTL tags and interpolations.
              For example: <code class="inline-code">&lt;#assign &lt;#-- a comment --&gt; x =
              3&gt;</code></p>
            </li>

            <li>
              <p>All letters and numbers are enabled in variable names,
              also <code class="inline-code">$</code> is allowed (as in Java programming
              language). Thus you can use accents, Arabic letters, Chinese
              letters, etc.</p>
            </li>

            <li>
              <p>String literals can be quoted with apostrophe-quote.
              <code class="inline-code">&quot;foo&quot;</code> and <code class="inline-code">&#39;foo&#39;</code> are
              equivalent.</p>
            </li>

            <li>
              <p>New <a href="ref_builtins_string.html">string
              built-ins</a>: <code class="inline-code">index_of</code>,
              <code class="inline-code">last_index_of</code>,
              <code class="inline-code">starts_with</code>, <code class="inline-code">ends_with</code>,
              <code class="inline-code">replace</code>, <code class="inline-code">split</code>,
              <code class="inline-code">chop_linebreak</code>,
              <code class="inline-code">uncap_first</code>.</p>
            </li>

            <li>
              <p>New <a href="ref_builtins_sequence.html">sequence
              built-ins</a>: <code class="inline-code">sort</code>,
              <code class="inline-code">sort_by</code>.</p>
            </li>

            <li>
              <p>New built-ins for experts to check the type of a variable.
              See: <a href="ref_builtins_expert.html#ref_builtin_isType"><code>is_<em>...</em></code>
              built-ins</a></p>
            </li>

            <li>
              <p>New built-in for experts to create a variable of certain
              Java <code class="inline-code">TemplateModel</code> implementation. See: <a href="ref_builtins_expert.html#ref_builtin_new"><code>new</code>
              built-in</a></p>
            </li>

            <li>
              <p>New built-in, <a href="ref_builtins_expert.html#ref_builtin_namespace"><code>namespace</code></a>,
              to get the namespace of a macro.</p>
            </li>

            <li>
              <p>New expression type: special variable expression. To
              prevent backward compatibility problems when we introduce new
              predefined variables, from now <a href="dgui_template_exp.html#dgui_template_exp_var_special">special variable
              expressions</a> are used to access them.</p>
            </li>

            <li>
              <p>New directives: <code class="inline-code">t</code>,
              <code class="inline-code">rt</code> and <code class="inline-code">lt</code> directives allow
              you to do explicit white-space removal in extreme FTL
              applications. For more information read <a href="ref_directive_t.html#ref.directive.t">the reference</a>.</p>
            </li>

            <li>
              <p><code class="inline-code">assign</code>, <code class="inline-code">local</code> and
              <code class="inline-code">global</code> now can capture the output generated
              be the nested template fragment into the variable. This
              deprecates <code class="inline-code">capture_output</code> transform. More
              information: <a href="ref_directive_assign.html#ref.directive.assign">assign
              directive reference</a></p>
            </li>

            <li>
              <p>Bulk assignments (as <code class="inline-code">&lt;#assign x=1, y=2,
              z=3&gt;</code>) no longer need colon to separate the
              assignments (as <code class="inline-code">&lt;#assign x=1 y=2 z=3&gt;</code>),
              although it is still allowed to preserve backward
              compatibility.</p>
            </li>

            <li>
              <p>Path that contains <code class="inline-code">//:</code> is considered as
              absolute path.</p>
            </li>

            <li>
              <p><code class="inline-code">include</code> and
              <code class="inline-code">transform</code> directives no longer need a
              semicolon to separate the template or transform name from the
              parameter list, although it is still allowed to preserve
              backward compatibility.</p>
            </li>

            <li>
              <p><code class="inline-code">#</code>-less tag syntax is deprecated (but
              still working). That is, you should write
              <code class="inline-code">&lt;#<em class="code-color">directive
              ...</em>&gt;</code> instead of
              <code class="inline-code">&lt;<em class="code-color">directive
              ...</em>&gt;</code>, and
              <code class="inline-code">&lt;/#<em class="code-color">directive
              ...</em>&gt;</code> instead of
              <code class="inline-code">&lt;/<em class="code-color">directive
              ...</em>&gt;</code>. For more info read: <a href="ref_depr_oldsyntax.html">模板语言参考 /废弃的 FTL 结构/老式 FTL 语法</a></p>
            </li>

            <li>
              <p><code class="inline-code">foreach</code> is depreciated (but still
              working). Use <a href="ref_directive_list.html#ref.directive.list"><code>list</code></a>
              instead.</p>
            </li>

            <li>
              <p>Bugfix: Undefined variables in hash and sequence
              constructors (as <code class="inline-code">[a, b, c]</code>) didn&#39;t caused
              errors.</p>
            </li>

            <li>
              <p>Bugfix: String concatenation had performance problem if
              there was multiple concatenations chained, as:
              <code class="inline-code">&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x</code>.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_242">Changes on the Java side</h2>


          <ul>
            <li>
              <p>Arbitrary JSP custom tags can be used as FreeMarker
              transforms in <code class="inline-code">FreemarkerServlet</code>-driven
              templates. More information: <a href="pgui_misc_servlet.html">程序开发指南/其它/在Servlet中使用FreeMarker</a></p>
            </li>

            <li>
              <p>Various improvements for
              <code class="inline-code">BeansWrapper</code>:</p>

              <ul>
                <li>
                  <p>The <code class="inline-code">BeansWrapper</code> no longer exposes
                  arbitrary objects as
                  <code class="inline-code">TemplateScalarModel</code>s, only
                  <code class="inline-code">java.lang.String</code> and
                  <code class="inline-code">Character</code> objects. This way, number
                  objects wrapped through <code class="inline-code">BeansWrapper</code> are
                  subject to FreeMarker&#39;s number formatting machinery. As a
                  side effect, non-string and non-number objects that were
                  previously accepted in equality and inequality operations
                  (because they had a string representation) will now cause
                  the engine to throw exception on comparison attempt.</p>
                </li>

                <li>
                  <p><code class="inline-code">java.lang.Character</code> objects are
                  exposed as scalars through
                  <code class="inline-code">BeansWrapper</code>.</p>
                </li>

                <li>
                  <p>Experimental feature: With the
                  <code class="inline-code">setSimpleMapWrapper</code> method of
                  <code class="inline-code">BeansWrapper</code> you can configure it to wrap
                  <code class="inline-code">java.util.Map</code>-s as
                  <code class="inline-code">TemplateHashModelEx</code>-s, and do not expose
                  the methods of the object.</p>
                </li>
              </ul>
            </li>

            <li>
              <p><code class="inline-code">TransformControl</code> interface (was
              experimental earlier): If the <code class="inline-code">Writer</code> returned
              by <code class="inline-code">TemplateTransformModel.getWriter</code>
              implements this interface, it can instruct the engine to skip or
              to repeat evaluation of the nested content, and gets notified
              about exceptions that are thrown during the nested content
              evaluation. Note that the <code class="inline-code">onStart</code> and
              <code class="inline-code">afterBody</code> methods now are allowed to throw
              <code class="inline-code">IOException</code>. For more information please read
              the API documentation.</p>
            </li>

            <li>
              <p>Localized lookup can be disabled with the new
              <code class="inline-code">Configuration</code> methods:
              <code class="inline-code">set/getLocalizedLookup</code>,
              <code class="inline-code">clearTemplateCache</code></p>
            </li>

            <li>
              <p>The new interface
              <code class="inline-code">freemarker.cache.CacheStorage</code> allows users to
              plug custom template caching strategies with the
              <code class="inline-code">cache_storage</code> setting. The core package now
              ships with two implementations:
              <code class="inline-code">SoftCacheStorage</code> and
              <code class="inline-code">StrongCacheStorage</code>. For more information
              read: <a href="pgui_config_templateloading.html">程序开发指南/配置(Configuration)/模板加载</a></p>
            </li>

            <li>
              <p>You can set settings with string name and string value
              with the new <code class="inline-code">setSetting(String key, String
              value)</code> method of <code class="inline-code">Configurable</code>
              super-classes (as <code class="inline-code">Configuration</code>). Also you
              can load settings from <code class="inline-code">.properties</code> file with
              the <code class="inline-code">setSettings</code> method.</p>
            </li>

            <li>
              <p>Other new <code class="inline-code">Configuration</code> methods:
              <code class="inline-code">clearTemplateCache</code>,
              <code class="inline-code">clearSharedVariables</code>,
              <code class="inline-code">getTemplateLoader</code>, and
              <code class="inline-code">clone</code>.</p>
            </li>

            <li>
              <p>Changes to <code class="inline-code">TemplateTransformModel</code>
              interface: <code class="inline-code">getWriter</code> can throw
              <code class="inline-code">IOException</code>, and can return
              <code class="inline-code">null</code> if the transform does not support body
              content.</p>
            </li>

            <li>
              <p>Till now
              <code class="inline-code">TemplateTransformModel.getWriter</code> has received
              null as parameter map if the transform was called without
              parameters. From now, it will receive an empty Map instead. Note
              that the previous API documentation didn&#39;t state that it always
              receives null if there are no parameters, so hopelessly only
              very few classes exploit this design mistake.</p>
            </li>

            <li>
              <p>Various improvements for
              <code class="inline-code">FreemarkerServlet</code>:</p>

              <ul>
                <li>
                  <p>The data-model now uses automatic scope discovery, so
                  writing
                  <code class="inline-code">Application.<em class="code-color">attrName</em></code>,
                  <code class="inline-code">Session.<em class="code-color">attrName</em></code>,
                  <code class="inline-code">Request.<em class="code-color">attrName</em></code>
                  is no longer mandatory; it&#39;s enough to write
                  <code class="inline-code"><em class="code-color">attrName</em></code>. For
                  more information <a href="pgui_misc_servlet.html#topic.servlet.scopeAttr">read this</a>.</p>
                </li>

                <li>
                  <p><code class="inline-code">FreemarkerServlet</code> now uses the
                  encoding of the template file for the output, unless you
                  specify the encoding in the <code class="inline-code">ContentType</code>
                  init-param, such as <code class="inline-code">text/html;
                  charset=UTF-8</code>.</p>
                </li>

                <li>
                  <p>All <code class="inline-code">Configuration</code> level settings
                  can by set with Servlet init-params
                  (<code class="inline-code">template_exception_handler</code>,
                  <code class="inline-code">locale</code>, <code class="inline-code">number_format</code>,
                  etc.).</p>
                </li>

                <li>
                  <p>The object wrapper the servlet internally uses is now
                  set as the default object wrapper for its
                  <code class="inline-code">Configuration</code> instance.</p>
                </li>

                <li>
                  <p>It no longer forces session creation for requests that
                  don&#39;t belong to an existing session, improving
                  scalability.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>JDOM independent XML-wrapping:
              <code class="inline-code">freemarker.ext.xml.NodeListModel</code> is a
              re-implementation of
              <code class="inline-code">freemarker.ext.jdom.NodeListModel</code> that does
              not rely on JDOM; you don&#39;t need JDOM .jar anymore. The new
              <code class="inline-code">NodeListModel</code> automatically uses W3C DOM,
              dom4j, or JDOM, depending on which library is available (that
              is, depending on what object do you pass to its
              constructor).</p>
            </li>

            <li>
              <p>Bugfix: <code class="inline-code">WebappTemplateLoader</code>: Template
              updating didn&#39;t worked correctly with Tomcat due the caching of
              resources. Now <code class="inline-code">WebappTemplateLoader</code> tries to
              access the resources directly as <code class="inline-code">File</code>, if it
              is possible, thus bypasses the caching.</p>
            </li>

            <li>
              <p>Various bug-fixes for
              <code class="inline-code">FreemarkerServlet</code>:</p>

              <ul>
                <li>
                  <p>The servlet now loads the correct template if it was
                  called through
                  <code class="inline-code">RequestDispatcher.include</code>.</p>
                </li>

                <li>
                  <p>The caching of <code class="inline-code">HttpServletRequest</code>
                  objects is now compliant with the servlet
                  specification.</p>
                </li>

                <li>
                  <p><code class="inline-code">TemplateException</code>s was suppressed
                  in certain situations resulting in half-rendered pages
                  without error message.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>Bugfix: FreeMarker didn&#39;t work if the
              <code class="inline-code">javax.servlet</code> classes was not available,
              because <code class="inline-code">Configuration</code> explicitly referred to
              <code class="inline-code">javax.servlet.ServletContext</code>.</p>
            </li>

            <li>
              <p>Bugfix: classes may were not found if they was available
              only in the <code class="inline-code">WEB-INF</code>, and FreeMarker tried to
              load the class dynamically.</p>
            </li>

            <li>
              <p>Bugfix: the <code class="inline-code">Template</code> constructor (and
              thus <code class="inline-code">Configuration.getTemplate</code>) sometimes
              threw <code class="inline-code">TokenMgrError</code> (a non-checked exception)
              instead of <code class="inline-code">ParseException</code>.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_243">Other changes</h2>


          <ul>
            <li>
              <p>The Web application related examples has been
              replaced.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_244">The history of the releases before the final version</h2>


          
            



<h3 class="content-header header-section3" id="autoid_245">Differences between the final and RC2 releases</h3>


            <ul>
              <li>
                <p>You can load settings from
                <code class="inline-code">.properties</code> file with the
                <code class="inline-code">setSettings</code> method of
                <code class="inline-code">Configuration</code> and other
                <code class="inline-code">Configurable</code> subclasses.</p>
              </li>

              <li>
                <p>New string built-in:
                <code class="inline-code">uncap_first</code></p>
              </li>

              <li>
                <p>Bugfix: When exposing an XML document to a template and
                accessing it with XPath using Jaxen a
                <code class="inline-code">ClassCastException</code> has occurred.</p>
              </li>

              <li>
                <p>Bugfix: The template cache has loaded templates with bad
                <code class="inline-code">Configuration</code> instance in certain
                situations if you use not the static default
                <code class="inline-code">Configuration</code> instance.</p>
              </li>
            </ul>
          

          
            



<h3 class="content-header header-section3" id="autoid_246">Differences between the RC2 and RC1 releases</h3>


            <ul>
              <li>
                <p>Non backward compatible change!:
                <code class="inline-code">FreemarkerServlet</code> now uses the encoding of
                the template file for the output, unless you specify the
                encoding in the <code class="inline-code">ContentType</code> init-param,
                such as <code class="inline-code">text/html; charset=UTF-8</code>.</p>
              </li>

              <li>
                <p>Non backward compatible change compared to RC1!: The
                <code class="inline-code">capture_output</code> transform creates variable
                in the current namespace (as <code class="inline-code">assign</code>
                directive) with the <code class="inline-code">var</code> parameter, not a
                global variable.</p>
              </li>

              <li>
                <p>The new and preferred way of number formatting with
                <code class="inline-code">string</code> built-in is
                <code class="inline-code">foo?string(format)</code>, instead of the less
                natural <code class="inline-code">foo?string[format]</code>.</p>
              </li>

              <li>
                <p>The <code class="inline-code">string</code> built-in works for boolean
                values. For example: <code class="inline-code">${spamFilter?string(&quot;enabled&quot;,
                &quot;disabled&quot;)}</code>. For more information <a href="ref_builtins_boolean.html#ref_builtin_string_for_boolean">read the
                reference</a>.</p>
              </li>

              <li>
                <p>The default strings for outputting boolean value using
                the <code class="inline-code">string</code> built-in can be set using the
                <code class="inline-code">boolean_format</code> setting.</p>
              </li>

              <li>
                <p>String literals can be quoted with apostrophe-quote.
                <code class="inline-code">&quot;foo&quot;</code> and <code class="inline-code">&#39;foo&#39;</code> are
                equivalent.</p>
              </li>

              <li>
                <p>The new interface
                <code class="inline-code">freemarker.cache.CacheStorage</code> allows users
                to plug custom template caching strategies with the
                <code class="inline-code">cache_storage</code> setting. The core package now
                ships with two implementations:
                <code class="inline-code">SoftCacheStorage</code> and
                <code class="inline-code">StrongCacheStorage</code>. For more information
                read: <a href="pgui_config_templateloading.html">程序开发指南/配置(Configuration)/模板加载</a></p>
              </li>

              <li>
                <p>You can set settings with string name and string value
                with the new <code class="inline-code">setSetting(String key, String
                value)</code> method of <code class="inline-code">Configurable</code>
                super-classes (as <code class="inline-code">Configuration</code>).</p>
              </li>

              <li>
                <p>Other new <code class="inline-code">Configuration</code> methods:
                <code class="inline-code">getTemplateLoader</code>,
                <code class="inline-code">clone</code>.</p>
              </li>

              <li>
                <p><code class="inline-code">assign</code>, <code class="inline-code">local</code> and
                <code class="inline-code">global</code> now can capture the output generated
                be the nested template fragment into the variable. This
                deprecates <code class="inline-code">capture_output</code> transform. More
                information: <a href="ref_directive_assign.html#ref.directive.assign">assign
                directive reference</a></p>
              </li>

              <li>
                <p>Other new <code class="inline-code">Configuration</code> methods:
                <code class="inline-code">getTemplateLoader</code>,
                <code class="inline-code">clone</code>.</p>
              </li>

              <li>
                <p>Changes to <code class="inline-code">TemplateTransformModel</code>
                interface: <code class="inline-code">getWriter</code> can throw
                <code class="inline-code">IOException</code>, and can return
                <code class="inline-code">null</code> if the transform does not support body
                content.</p>
              </li>

              <li>
                <p>Till now
                <code class="inline-code">TemplateTransformModel.getWriter</code> has
                received null as parameter map if the transform was called
                without parameters. From now, it will receive an empty Map
                instead. Note that the previous API documentation didn&#39;t state
                that it always receives null if there are no parameters, so
                hopelessly only very few classes exploit this design
                mistake.</p>
              </li>

              <li>
                <p>Changes to <code class="inline-code">TemplateControl</code> interface:
                <code class="inline-code">onStart</code> and <code class="inline-code">afterBody</code>
                methods are now allowed to throw
                <code class="inline-code">IOException</code>.</p>
              </li>

              <li>
                <p>Path that contains <code class="inline-code">//:</code> is considered
                as absolute path.</p>
              </li>

              <li>
                <p>New <a href="ref_builtins_string.html">string
                built-ins</a>: <code class="inline-code">index_of</code>,
                <code class="inline-code">last_index_of</code>,
                <code class="inline-code">starts_with</code>, <code class="inline-code">ends_with</code>,
                <code class="inline-code">replace</code>, <code class="inline-code">split</code>,
                <code class="inline-code">chop_linebreak</code>.</p>
              </li>

              <li>
                <p>New <a href="ref_builtins_sequence.html">sequence
                built-ins</a>: <code class="inline-code">sort</code>,
                <code class="inline-code">sort_by</code>.</p>
              </li>

              <li>
                <p>All <code class="inline-code">Configuration</code> level settings can
                by set with Servlet init-params
                (<code class="inline-code">template_exception_handler</code>,
                <code class="inline-code">locale</code>, <code class="inline-code">number_format</code>,
                etc.).</p>
              </li>

              <li>
                <p>Bugfix: classes may were not found if they was available
                only in the <code class="inline-code">WEB-INF</code>, and FreeMarker tried
                to load the class dynamically.</p>
              </li>

              <li>
                <p>Bugfix: <code class="inline-code">setLocalizedLookup(false)</code> of
                <code class="inline-code">Configuration</code> was overridden when you have
                called <code class="inline-code">setTemplateLoader</code>.</p>
              </li>

              <li>
                <p>Bugfix: String concatenation had performance problem if
                there was multiple concatenations chained, as:
                <code class="inline-code">&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x+&quot;a&quot;+x</code>.</p>
              </li>

              <li>
                <p>Bugfix: white-space stripping was not worked with tags
                spanning over multiple lines.</p>
              </li>

              <li>
                <p>Bugfix: Removing several dependencies on JDK 1.3, so
                FreeMarker can be build for JDK 1.2.2.</p>
              </li>
            </ul>
          

          
            



<h3 class="content-header header-section3" id="autoid_247">Differences between the Preview 2 and RC1 releases</h3>


            <ul>
              <li>
                <p><code class="inline-code">ftl</code> is now stricter, and does not
                allow custom parameters. To associate custom attributes to
                templates, we may add a new directive later, if there is a
                demand for it.</p>
              </li>

              <li>
                <p><code class="inline-code">escape</code> directive does not affect
                numerical interpolations
                (<code class="inline-code">#{<em class="code-color">...</em>}</code>)
                anymore, as it has caused errors with string escapes as
                <code class="inline-code">?html</code>.</p>
              </li>

              <li>
                <p>The <code class="inline-code">normalizeName</code> method of
                <code class="inline-code">freemarker.cache.TemplateLoader</code> has been
                removed, because it has caused too many complications.
                Instead, normalization happens on a single point in the
                <code class="inline-code">TempateCache</code>. In consequence, FreeMarker is
                now stricter about the format of template paths, as things
                like <code class="inline-code">/../</code> are interpreted by the
                core.</p>
              </li>

              <li>
                <p>Experimental feature: With the
                <code class="inline-code">setSimpleMapWrapper</code> method of
                <code class="inline-code">BeansWrapper</code> you can configure it to wrap
                <code class="inline-code">java.util.Map</code>-s as
                <code class="inline-code">TemplateHashModelEx</code>-s, and do not expose
                the methods of the object.</p>
              </li>

              <li>
                <p>New <code class="inline-code">Configuration</code> methods:
                <code class="inline-code">set/getLocalizedLookup</code>,
                <code class="inline-code">clearTemplateCache</code>,
                <code class="inline-code">clearSharedVariables</code>.</p>
              </li>

              <li>
                <p>More cleanups in the <code class="inline-code">Environment</code>
                API.</p>
              </li>

              <li>
                <p>Better JSP standard compliance: JSP page-scope variables
                are the global variables that were created in the template
                (not the variables of the data-model).</p>
              </li>

              <li>
                <p>JDOM independent XML-wrapping:
                <code class="inline-code">freemarker.ext.xml.NodeListModel</code> is a
                re-implementation of
                <code class="inline-code">freemarker.ext.jdom.NodeListModel</code> that does
                not rely on JDOM; you don&#39;t need JDOM .jar anymore. The new
                <code class="inline-code">NodeListModel</code> automatically uses W3C DOM,
                dom4j, or JDOM, depending on which library is available (that
                is, depending on what object do you pass to its
                constructor).</p>
              </li>

              <li>
                <p>Bugfix: <code class="inline-code">WebappTemplateLoader</code>:
                Template updating didn&#39;t worked correctly with Tomcat due the
                caching of resources. Now
                <code class="inline-code">WebappTemplateLoader</code> tries to access the
                resources directly as <code class="inline-code">File</code>, if it is
                possible, thus bypasses the caching.</p>
              </li>

              <li>
                <p>Bugfix: Templates loaded with
                <code class="inline-code">MultiTemplateLoader</code> subclasses was removed
                from the template cache after the template update delay has
                elapsed (5 seconds by default) even if the template file was
                unchanged. This can cause lot of extra load for a high-traffic
                server if you have many templates or if the template update
                delay was set to 0 second.</p>
              </li>

              <li>
                <p>Bugfix: Undefined variables in hash and sequence
                constructors (as <code class="inline-code">[a, b, c]</code>) didn&#39;t caused
                errors.</p>
              </li>
            </ul>
          

          
            



<h3 class="content-header header-section3" id="autoid_248">Differences between the Preview 1 and Preview 2
            releases</h3>


            <ul>
              <li>
                <p>All 16-bit Unicode letters and numbers are allowed in
                identifiers, as well as the <code class="inline-code">$</code> character (as
                in Java programming language). Thus you can use accented
                letters, Arabic letters, Chinese letters, etc. as identifiers
                in templates</p>
              </li>

              <li>
                <p>Macros now can create loop variables for the nested
                content. For more information <a href="dgui_misc_userdefdir.html#dgui_misc_userdefdir_loopvar">read
                this</a>.</p>
              </li>

              <li>
                <p>New directives: <code class="inline-code">t</code>,
                <code class="inline-code">rt</code> and <code class="inline-code">lt</code> directives
                allow you to do explicit white-space removal in extreme FTL
                applications. For more information read <a href="ref_directive_t.html#ref.directive.t">the reference</a>.</p>
              </li>

              <li>
                <p>The syntax of assignment-with-namespace has changed from
                <code class="inline-code">&lt;#assign foo=123 namespace=myLib&gt;</code>) to
                <code class="inline-code">&lt;#assign foo=123 in myLib&gt;</code>, since the
                previous syntax was confusing because its similarity to a
                bulk-assignment.</p>
              </li>

              <li>
                <p>Bulk assignments (as <code class="inline-code">&lt;#assign x=1, y=2,
                z=3&gt;</code>) no longer need colon to separate the
                assignments (as <code class="inline-code">&lt;#assign x=1 y=2
                z=3&gt;</code>), although it is still allowed to preserve
                backward compatibility.</p>
              </li>

              <li>
                <p>Positional parameter passing is supported for macro
                calls as shorthand form of normal named parameter passing. For
                more details read <a href="ref_directive_userDefined.html#ref_directive_userDefined_positionalParam">read the
                reference</a>.</p>
              </li>

              <li>
                <p>New built-in, <code class="inline-code">namespace</code>, to get the
                namespace of the currently executing macro.</p>
              </li>

              <li>
                <p><code class="inline-code">TransformControl</code> interface (was
                experimental earlier): If the <code class="inline-code">Writer</code>
                returned by
                <code class="inline-code">TemplateTransformModel.getWriter</code> implements
                this interface, it can instruct the engine to skip or to
                repeat evaluation of the nested content, and gets notified
                about exceptions that are thrown during the nested content
                evaluation. For more information please read the API
                documentation.</p>
              </li>

              <li>
                <p>Jython wrapper can now wrap arbitrary Java objects, not
                only <code class="inline-code">PyObject</code>-s. If an object is passed to
                the wrapper that is neither a
                <code class="inline-code">TemplateModel</code>, nor a
                <code class="inline-code">PyObject</code>, it is first coerced into a
                <code class="inline-code">PyObject</code> using Jython&#39;s own wrapping
                machinery, and then wrapped into a
                <code class="inline-code">TemplateModel</code> as any other
                <code class="inline-code">PyObject</code>.</p>
              </li>

              <li>
                <p>Some cleanups in the <code class="inline-code">Environment</code>
                API.</p>
              </li>

              <li>
                <p>The Web application related examples has been
                replaced.</p>
              </li>

              <li>
                <p>Bugfix: Templates loaded with
                <code class="inline-code">URLTemplateLoader</code> subclasses was removed
                from the template cache after the template update delay has
                elapsed (5 seconds by default) even if the template file was
                unchanged. This can cause lot of extra load for a high-traffic
                server if you have many templates or if the template update
                delay was set to 0 second.</p>
              </li>

              <li>
                <p>Bugfix: <code class="inline-code">FreeMarkerServlet</code> has thrown
                <code class="inline-code">ServletException</code> even if a debug
                <code class="inline-code">TemplateException</code> handler was in use (so
                you may got Error 500 page instead of debug
                information).</p>
              </li>
            </ul>
          
        <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_2_1.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_1_5.html"><span>Next</span></a></div></div></div></div>      </div>
    </div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="http://freemarker.org/index.html">What is FreeMarker?</a></li><li><a href="http://freemarker.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="http://freemarker.org/history.html">About us</a></li><li><a itemprop="license" href="app_license.html">License</a></li></ul></div><div class="column"><h3 class="column-header">Handy stuff</h3><ul><li><a href="http://freemarker-online.kenshoo.com/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/nanlei/freemarker/tree/manual-zh-2.3-gae/src/manual">Chinese Manual on Github</a></li><li><a href="https://github.com/freemarker/freemarker">FreeMarker on Github</a></li><li><a href="https://twitter.com/freemarker">Follow us on Twitter</a></li><li><a href="https://sourceforge.net/p/freemarker/bugs/new/">Report a bug</a></li><li><a href="http://stackoverflow.com/questions/ask?tags=freemarker">Ask a question</a></li><li><a href="http://freemarker.org/mailing-lists.html">Mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/freemarker/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="http://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"><p><span class="generated-for-product">Generated for: Freemarker 2.3.23</span><span class="last-updated"> Last generated:
<time itemprop="dateModified" datetime="2015-09-18T14:38:51Z" title="Friday, September 18, 2015 2:38:51 PM GMT">2015-09-18 14:38:51 GMT</time></span></p> <p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2015
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="http://freemarker.org">The FreeMarker Project</a>. All rights reserved. </p>
</div></div></div></body>
</html>
